home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk1 / semaphorestutor / sigsem.c < prev   
C/C++ Source or Header  |  1995-03-18  |  4KB  |  202 lines

  1. /*
  2.  * This program plays around with signal semaphores...
  3.  *
  4.  * Thanks to C-A for providing the new bindings & AddSemaphore code
  5.  *
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <exec/nodes.h>
  10. #include <exec/ports.h>
  11. #include <exec/semaphores.h>
  12. #include <exec/memory.h>
  13. #include <exec/execbase.h>
  14.  
  15. struct XSSemaphore {
  16.     struct SignalSemaphore s;
  17.     WORD Users;
  18. };
  19.  
  20. void *AllocMem();
  21. void cleanup();
  22. void DeleteSSemaphore();
  23. struct SignalSemaphore *myFindSemaphore();
  24. struct XSSemaphore *CreateSSemaphore();
  25.  
  26. struct XSSemaphore *sem = 0;
  27.  
  28. /* I made this extended semaphore so that there is an easy way to
  29.  * keep track of when it is safe to delete it.  If anyone can think
  30.  * of a better way to do this, I'd love to hear it.
  31.  */
  32.  
  33. extern int Enable_Abort;
  34.  
  35. main()
  36. {
  37.     int i;
  38.     Enable_Abort = 0;
  39.  
  40.     /* the existance check/creation must be atomic --> Forbid/Permit */
  41.  
  42.     Forbid();
  43.  
  44.     if (!(sem = (struct XSSemaphore *)myFindSemaphore("sigSemaphore")))
  45.         sem = CreateSSemaphore("sigSemaphore",0);
  46.     else
  47.         sem->Users++;
  48.  
  49.     Permit();
  50.  
  51.     if (!sem) {
  52.         printf("Error, can't find *or* create semaphore\n");
  53.         cleanup();
  54.         exit(100);
  55.     }
  56.  
  57.     for (i=0;i<5;i++) {
  58.  
  59.         /* get use of the semaphore */
  60.         ObtainSemaphore(sem);
  61.  
  62.         /* we now have exclusive access */
  63.  
  64.         printf("\nTask $%06x owns the semaphore\n",FindTask(0));
  65.  
  66.         /* pretend to so some action requiring semaphore */
  67.         Delay(1 + (rand()&31));
  68.  
  69.         printf("\t\t...semaphore now released\n");
  70.  
  71.         /* yield control to someone else */
  72.         ReleaseSemaphore(sem);
  73.  
  74.         /* pretend to so some action not requiring semaphore */
  75.         Delay(1 + (rand()&31));
  76.  
  77.     }
  78.  
  79.     cleanup();
  80. }
  81.  
  82. void cleanup()
  83. {
  84.     if (sem) {
  85.         /* the user check/delete must be atomic --> Forbid/Permit */
  86.  
  87.         Forbid();
  88.         if (--sem->Users == 0)
  89.             DeleteSSemaphore(sem);
  90.         Permit();
  91.  
  92.         sem = 0;
  93.     }
  94. }
  95.  
  96. struct XSSemaphore *CreateSSemaphore(name,pri)
  97. char *name;
  98. int pri;
  99. {
  100.     struct XSSemaphore *sem;
  101.     char *buf;
  102.  
  103.     sem = AllocMem(sizeof(struct XSSemaphore), MEMF_PUBLIC|MEMF_CLEAR);
  104.  
  105.     if (!sem) return(0);
  106.  
  107.     sem->s.ss_Link.ln_Type = NT_SIGNALSEM;
  108.     sem->s.ss_Link.ln_Pri  = pri;
  109.  
  110.     /* Note that the name must be copied as the original creator
  111.      * of the semaphore might exit.  We can't leave a pointer to
  112.      * the original data segment lying around after the program
  113.      * has exited.  
  114.      */
  115.     if (name) {
  116.         buf = AllocMem(strlen(name)+1, MEMF_PUBLIC);
  117.         if (!buf) {
  118.             FreeMem(sem, sizeof(struct XSSemaphore));
  119.             return(0);
  120.         }
  121.         strcpy(buf,name);
  122.         sem->s.ss_Link.ln_Name = buf;
  123.         myAddSemaphore(sem);
  124.     }
  125.     else
  126.         InitSemaphore(sem);
  127.  
  128.     sem->Users = 1;
  129.  
  130.     return(sem);
  131. }
  132.  
  133. void DeleteSSemaphore(sem)
  134. struct XSSemaphore *sem;
  135. {
  136.     char *name;
  137.  
  138.     if (!sem) return;
  139.  
  140.     name = sem->s.ss_Link.ln_Name;
  141.  
  142.     if (name) {
  143.         myRemSemaphore(sem);
  144.         FreeMem(name, strlen(name) + 1 );
  145.     }
  146.  
  147.     FreeMem(sem, sizeof(struct XSSemaphore));
  148. }
  149.  
  150.  
  151. /* The bindings for "AddSemaphore" are broken in 1.2 Amiga.lib
  152.  *
  153.  * Dale's handcrafted AddSemaphore(). 
  154.  */
  155.  
  156. myAddSemaphore(ss)
  157. struct SignalSemaphore *ss;
  158. {
  159.     extern struct ExecBase *SysBase;
  160.  
  161.     InitSemaphore(ss);
  162.     Forbid();
  163.     Enqueue(&SysBase->SemaphoreList,ss);
  164.     Permit();
  165. }
  166.  
  167. /* The "C" interface code for the following semaphore routines is broken in
  168.  * Amiga.lib and in the Aztec C release 3.4a.
  169.  *
  170.  * @ Lattice people should cut and paste the assembler into a separate file.
  171.  */
  172.  
  173. #if AZTEC_C     
  174. #asm
  175. ; The exec.library function "AddSemaphore" is broken in KickStart rel. 33.180
  176. ;
  177. ; The Aztec bindings think that they should be using a0 to pass the
  178. ; argument instead of a1.  This is likely the problem with the Lattice
  179. ; bindings.  The Exec AddSemaphore function seems to be just plain broken.
  180. ;
  181. ;        -Rico
  182.         
  183.         XREF    _SysBase
  184.         XREF    _LVOFindSemaphore
  185.     XREF    _LVORemSemaphore
  186.  
  187.  
  188.     XDEF    _myFindSemaphore
  189.     XDEF    _myRemSemaphore
  190.  
  191. _myFindSemaphore:
  192.     move.l     4(sp),a1
  193.         move.l     _SysBase,a6
  194.     jmp     _LVOFindSemaphore(a6)
  195.  
  196. _myRemSemaphore:
  197.     move.l     4(sp),a1
  198.         move.l     _SysBase,a6
  199.     jmp     _LVORemSemaphore(a6)
  200. #endasm
  201. #endif
  202.